import pygame, sys, os
from pygame.locals import *
from time import sleep                      

class UNIDAD_CONTROL:
	#==============================================================================================================================================================================
	def DECODIFICAR(self, primero_menor=None):
		if self.operacion == " NOT ":		codop = self.RAM[1][16:20]       #  es la posicion del codigo de oprecion ubicado en mem RAM -- elegido por el usuario
		else:								codop = self.RAM[2][16:20]       #  es la posicion del codigo de oprecion ubicado en mem RAM -- elegido por el usuario
		if codop == "0010":				self.resultado = self.SUMA_comp_a_2(self.RAM[0][:-1], self.RAM[1][:-1])
		elif codop == "0100":			self.resultado = self.AND(self.RAM[0][:-1], self.RAM[1][:-1])
		elif codop == "0101":			self.resultado = self.OR(self.RAM[0][:-1], self.RAM[1][:-1])
		elif codop == "0110":			self.resultado = self.NOT(self.RAM[0][:-1])
		elif codop == "0011":
			if self.RAM[1][:-1] == ("0"*32):		self.resultado = self.SUMA_comp_a_2((self.RAM[0][:-1]), self.RAM[1][:-1]) #  ...
			else:									self.resultado = self.SUMA_comp_a_2((self.RAM[0][:-1]), self.comp_a_2(self.RAM[1][:-1])) #  ...
			if self.RAM[0] < self.RAM[1]:     		primero_menor , self.resultado = 1 , self.comp_a_2(self.resultado)  #  si el primer valor es < al segundo . . .
		self.ESCRIBIR_SALIDA(primero_menor) , self.ESCRIBIR_RAM() , self.MOSTRAR_RESULTADO() , self.MOSTRAR_IMAGEN("FONDO/memory.jpg",(0,487))		
		L = [(self.INICIO,self.boton_inicio,150,328,480,550),(self.MOSTRAR_Memoria,self.boton_memoria,370,548,480,550),(self.SALIR,self.boton_salir,590,768,480,550)]
		self.EVENTO_mouse(L)       #  llamamos al metodo EVENTO_mouse() y le pasamos la lista L como parametro          		
	#==============================================================================================================================================================================
	def ESCRIBIR_SALIDA(self, primero_menor=None):
		s = open("SALIDA.txt","w")        #  abrimos el archivo "SALIDA.txt" en modo escritura  ("w" --- sobrescribe el archivo) 
		if primero_menor:                 #  si primero_menor . . . . . . quiere decir que el primer valor es < al segundo
			s.write("-" + str( self.BINARIO_A_DECIMAL(self.resultado))) # si re es verdadero le agrego un signo negativo al resultado y lo ecribo en "SALIDA.txt"
			self.resultado = list(str(self.resultado))            #   convierto el resultado a string y luego a lista
			self.resultado[0] = "1"                         	  #   ya que el resultado es negativo --- le cambio el bit mas significativo por un 1(uno)
			self.resultado = "".join(self.resultado)              #   convierto el resultado a string
		else:		s.write(str( self.BINARIO_A_DECIMAL(self.resultado))) ,  s.close()#  sino lo convierto a decimal y lo escribo en el archivo de salida  y  cierro el archivo
	#==============================================================================================================================================================================
	def ESCRIBIR_RAM(self):
		ram = open("RAM.txt","a")		   										#  abrimos el archivo "RAM.txt" en modo escritura  ("a" --- no sobrescribe el archivo) 
		ram.write(str(self.resultado) +"\n")    										#  escribo el resutado en memoria 
		for i in range(4092):		ram.write(self.DECIMAL_A_BINARIO(0)+"\n")       #  completo la memoria con 46 palabras ( todas con 0 )
		ram.close()                                       						#  cerramos el archivo para que se guarden los cambios
	#==============================================================================================================================================================================
	#----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----

class ENTRADA_SALIDA(UNIDAD_CONTROL): #  esta clase heredad de la clase UNIDAD_CONTROL
	#==============================================================================================================================================================================
	def INPUT_OUTPUT(self):        #   se muestran 2 imagenes al comienzo
		self.MOSTRAR_IMAGEN("FONDO/primero.jpg",(0,0))
		self.IMPRIMIR_texto("RESULTADO " ,(340,50), self.fuente[1], "green") , self.IMPRIMIR_texto("OPERACION: " + self.operacion,(260,120), self.fuente[1], "blue")
		f = open("ENTRADA.txt")                                                      #  abre el archivo "ENTRADA.txt" en modo lectura
		valores = f.readlines()                                                      #  guarda cada linea como un elemento --- en una lista llamada valores
		#~ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
		dic = {" SUMA ":"0010" , " RESTA ":"0011" , " AND ":"0100" , " OR ":"0101" ," NOT ":"0110"}# diccionario para las operaciones
		ram = open("RAM.txt","w")													 #  abre el archivo "SALIDA.txt" en modo escritura  ("w" --- sobrescribe el archivo)
		n_1 = self.DECIMAL_A_BINARIO(valores[0][:-1])
		ram.write(n_1+"\n")
		if self.operacion != " NOT ":                      
			n_2 = self.DECIMAL_A_BINARIO(valores[1][:-1])    #  se convierten los 2 numeros ingresados a binario
			ram.write(n_2+"\n")				            	 #  se escriben los operando en memoria
			ram.write("0001" + self.DECIMAL_A_BINARIO(0)[-12:] +  dic[self.operacion] + self.DECIMAL_A_BINARIO(1)[-12:] + "\n")# cargo los codop y las direcciones en memoria
		else:	ram.write("0001" + self.DECIMAL_A_BINARIO(0)[-12:] +  dic[self.operacion] + self.DECIMAL_A_BINARIO(0)[-12:] + "\n")# cargo los codop y las direcciones en memoria
		ram.close()
		#~ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
		f = open("RAM.txt")																		     #  abre el archivo "RAM.txt" en modo lectura
		self.RAM = f.readlines()																			 #  guarda cada linea como un elemento --- en una lista llamada RAM
		self.IMPRIMIR_texto(self.RAM[0],(288,210), self.fuente[0], "white")
		if self.operacion != " NOT ":
			self.MOSTRAR_IMAGEN("FONDO/segundo.jpg",(0,246)) , self.IMPRIMIR_texto("OPERACION: " + self.operacion,(260,120), self.fuente[1], "blue") 		
			self.IMPRIMIR_texto(self.RAM[1],(288,270), self.fuente[0], "white")#  se muestran los dos valores en binario
		self.DECODIFICAR()    #  llamamos al metodo DECODIFICAR() 
	#==========================================================================================================================================================
	def CARGAR_INPUT(self):				
		self.cargar_input += 1      #  self.cargar_input  se incrementa en 1 ----- cada vez que se llama al metodo CARGAR_INPUT()
		if self.cargar_input == 0:  self.INPUT("FONDO/primero.jpg",0,0,288,210)	#  si self.cargar_input == 0  se dirige al metodo self.INPUT() con parametros especificos
		if self.cargar_input == 1:	self.INPUT("FONDO/segundo.jpg",0,246,288,270) #  si self.cargar_input == 1  se dirige al metodo self.INPUT() con otros parametros
		if self.cargar_input == 2:  self.INPUT_OUTPUT()  #  si self.cargar_input == 2 quiere decir que ya se han ingresado los 2 valores - se dirige al metodo self.INPUT_OUTPUT()
	#==========================================================================================================================================================
	def INPUT(self, imagen, x, y, cad_x, cad_y, si=True):																				    #       
		pygame.mouse.set_visible(False), self.MOSTRAR_IMAGEN(imagen,(x,y)) , self.OPERACION() , self.IMPRIMIR_OPERACION()   # se muestra la imagen y se imprime la operacion seleccionada
		self.IMPRIMIR_texto("OPERACION: " + self.operacion,(260,120), self.fuente[1], "blue")
		while si:                          #  comienza el loop
			for evento in pygame.event.get():    #  se recorren los eventos de pygame
				if evento.type == KEYDOWN:          #   si el evento corresponde a una tecla presionada . . .
					if evento.key in [ K_0, K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9 ]:  # solamente si la tecla presionada es un numero . . .
						if len(self.cadena)<9:    self.cadena += evento.unicode  # si la cadena tiene menos de 9 caracteres    # a la cadena actual se le agrega el numero presionado
					if evento.key == K_BACKSPACE:      self.cadena = self.cadena[:-1]   #  si presiona la tecla BORRAR se elimina el ultimo caracter de la cadena
					if evento.key == K_RETURN:            #  si presiona la tecla ENTER
						if len(self.cadena) > 0:           #  si la cadena no esta vacia
							if imagen == "FONDO/primero.jpg":      #  si la imagen es "primero.jpg" entonces se trata del primer valor
								f = open("ENTRADA.txt","w")             #  se abre el archivo "ENTRADA.txt" en modo escritura (sobreescribe)
								f.write(self.cadena + "\n"), f.close()  #  se almacena la cadena ingresada   y   se cierra el archivo
								if self.operacion == " NOT ":           # si la operacion es NOT
									si = False
									self.INPUT_OUTPUT()                 #  ya que para not solo se nesecita un valor --- vamos directamente al metodo INPUT_OUTPUT()
							if imagen == "FONDO/segundo.jpg":      #  si la imagen es "segundo.jpg" entonces se trata del segundo valor
								f = open("ENTRADA.txt","a")             #  se abre el archivo "ENTRADA.txt" en modo escritura (escribe desde el final)
								f.write(self.cadena + "\n"), f.close()  #  se almacena la cadena ingresada	 y   se cierra el archivo			
							self.cadena , si = "" , False                #  la cadena vualve a ser vacia
							self.CARGAR_INPUT()              #  se dirige al metodo CARGAR_INPUT()
					if evento.key == K_ESCAPE: self.SALIR()              #  si presiona la tecla ESCAPE finaliza el programa
					if evento.key == K_SPACE: self.INICIO()              #  si presiona la tecla SPACE vuelve al inicio
			self.PRINT_cadena(self.cadena,cad_x, cad_y)      #  se imprime la cadena mientras el usuario va escribiendo													
	#==========================================================================================================================================================
	def MOSTRAR_RESULTADO(self):
		dic = {" SUMA ":"+" , " RESTA ":"-" , " AND ":"and" , " OR ":"or" ," NOT ":"not"}   	          # diccionario para mostrar el rasultado
		s , f = open("SALIDA.txt") , open("ENTRADA.txt")    										      #  abrimos los archivos "SALIDA.txt" y "ENTRADA.txt" en modo lectura
		F = f.readlines()																				  #  lista con los 2 valores ingresados
		if self.operacion == " NOT ":
			self.IMPRIMIR_texto("   Binario : ",(84,270), self.fuente[1], "maroon"), self.IMPRIMIR_texto(str(self.resultado) + " ",(288,280), self.fuente[0], "white")# muestro el result en pantalla (binario)
			self.IMPRIMIR_texto("  Decimal :  ", (75,340), self.fuente[1], "yellow"), self.IMPRIMIR_texto("  %s %s = %s " % (dic[self.operacion],F[0][:-1],s.readline()),(288,350), self.fuente[0], "white")# muestro el result en pantalla (decimal)
		else:
			self.IMPRIMIR_texto("   Binario :  ",(84,320), self.fuente[1], "maroon"), self.IMPRIMIR_texto( str(self.resultado) + " ",(288,330), self.fuente[0], "white")	# muestro el result en pantalla (binario)	
			self.IMPRIMIR_texto("  Decimal :  ",(75,380), self.fuente[1], "yellow"), self.IMPRIMIR_texto(" %s %s %s = %s " % (F[0][:-1],dic[self.operacion],F[1][:-1],s.readline()),(288,390), self.fuente[0], "white")# muestro el result en pantalla (decimal)
	#==============================================================================================================================================================================
	def MOSTRAR_Memoria(self):
		if self.operacion == " NOT ":		self.MOSTRAR_IMAGEN("FONDO/bits_not.jpg",(0,0))         #   segun la operacion ... se muestra una imagen u otra
		else:								self.MOSTRAR_IMAGEN("FONDO/bits_!=_not.jpg",(0,0))
		ram = open("RAM.txt")		   																#  abrimos el archivo "RAM.txt" en modo lectura
		memoria , x, y = ram.readlines() , 0, 0														#  memoria es una lista con las palabras que contiene la RAM
		for palabra in memoria[:5]:                                                                 #  se van a imprimir solo 5 palabras de la RAM
			for bit in palabra[:-1]:                                                                #  se recorre cada palabra menos el ultimo caracter
				self.IMPRIMIR_texto(bit+" ",(77+x,112+y), self.fuente[0], "white")                  #  se imprime 
				x += 25                                                                             #  x se incrementa en 25 para el desplazamiento de los bits
			x , y = 0 , y + 40	                                                                    #  x vuelve a 0(cero) ---- y se incrementa en 40
		self.MOSTRAR_IMAGEN("FONDO/bits_1.jpg",(0,290)),     self.MOSTRAR_IMAGEN("FONDO/codop.jpg",(620,410))  #  se muestran 2 imagenes
		L = [(self.INICIO,self.boton_inicio,100,278,490,560),(self.SALIR,self.boton_salir,330,508,490,560)]
		self.EVENTO_mouse(L)                				#  llamamos al metodo EVENTO_mouse() y le pasamos la lista L como parametro    
		#~ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------   
		   #~ AQUI FINALIZA EL PROGRAMA ------ el usuario tiene 2 opciones ---- SALIR o volver al INICIO
	#==============================================================================================================================================================================
	def DECIMAL_A_BINARIO(self,decimal):
		lis, decimal = [], int(decimal)              # definimos una lista vacia y convertimos la cadena a entero
		if decimal == "1":  return "0"*31 + "1"      # si el decimal es = a 1(uno) retornamos el num uno en binario representado en 32 bits
		while len(lis) < 32:                         # mientras la lista contenga menos de 32 numeros . . . 
			lis.append(str(decimal%2))               # agregamos a la lista el resto que nos queda en la division del numero decimal y 2 
			decimal = decimal/2                      # dividimos entre 2 al num decimal
		return "".join(lis)[::-1]                    # retornamos la lista que contiene el numero binario --- en forma de cadena invertida para que se lea correctamente
	#==========================================================================================================================================================
	def BINARIO_A_DECIMAL(self, binario):
		decimal, binario = 0, binario[::-1]       #  inicio un contador "decimal" en 0 (cero) ------ invierto la cadena "binario" y empiezo por el bit -significat.
		for x in range(len(binario)):             #  x recorre un rango desde 0(cero) hasta el total de caracteres que tenga "binario"
			decimal += int(binario[x]) * (2**x)   #  se suma a decimal -- el producto entre cada binario y (2**x) -- x va a ser 0,1,2,3,4........  
		return decimal                            #  devolvemos el binario convertido a decimal		
	#==============================================================================================================================================================================
	#----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----

class ALU:
	#==============================================================================================================================================================================
	def SUMA_comp_a_2(self,a,b):
		a , b = a[::-1], b[::-1]                                                   #  invertimos los 2 valores para trabajar correctamente
		lista , res , c  = [] , [] , 0                                             #  establecemos 3 variables --- 2 listas vacias y 1 contador
		for x in range(len(a)):				lista.append( [int(a[x]),int(b[x])] )  #  agrego a la lista, otra lista con 2 bits (uno de cada numero binario)                
		while c < 32:                                                              #  mientras c < 32 . . .
			if sum(lista[c]) == 0:          res.append("0")                           #  si la suma entre los 2 bits da 0(cero) -- se agrega un 0(cero) a "res"
			elif sum(lista[c]) == 1:        res.append("1")                           #  si la suma entre los 2 bits da 1(uno)  -- se agrega un 1(uno) a "res"
			elif sum(lista[c]) == 2:                                                  #  si la suma entre los 2 bits da 2(dos) . . . 
				if c == 31:                 res.append("0")                             #  si c == 31 -- se agrega un 0(cero) a "res"
				else:                       res.append("0"),  lista[c+1].append(1)       #  sino se agrega un 0(cero) a "res" y un 1(uno) a lista[c+1]
			elif sum(lista[c]) == 3:                                                  #  si la suma entre los 2 bits da 3(tres) . . . 
				if c == 31:                 res.append("1")                             #  si c == 31 -- se agrega un 1(uno) a "res"
				else:                       res.append("1"),  lista[c+1].append(1)       #  sino se agrega un 1(uno) a "res" y un 1(uno) a lista[c+1]
			c += 1                                                                     # se incrementa el contador en uno
		return "".join(res)[::-1]            #  se retorna la lista en forma de cadena
	#==============================================================================================================================================================================
	def comp_a_2(self,a):
		a = a[::-1]   #  invertimos el binario
		nA , pos = [] , a.index("1")          #  pos contiene la posicion del num 1 en la cadena "a" 
		for x in range(pos):     nA.append("0") #  agregamos a nA una cantidad de ceros hasta llegar a la posicion del num 1
		nA.append("1")                          #  agregamos a nA un 1(uno)
		for z in a[pos+1:len(a)+1]:           #  desde la siguiente posicion del 1(uno)  invertimos (si es un 1 agregamos un cero)y (si es un cero agregamos un uno)
			if z == "1":    nA.append("0")
			if z == "0":    nA.append("1")
		return "".join(nA)[::-1]              #  retornamos la lista del complemento a 2 --- en forma de cadena invertida
	#==============================================================================================================================================================================
	def AND(self, a, b):
		lista , res , c  = [] , [] , 0                                             #  establecemos 3 variables --- 2 listas vacias y 1 contador
		for x in range(len(a)):             lista.append( [int(a[x]),int(b[x])] )  #  agrego a la lista, otra lista con 2 bits (uno de cada numero binario)                
		while c < 32:                                                              #  mientras c < 32 . . .
			if sum(lista[c]) == 2:        res.append("1")                             # si los 2 bits son 1(uno) se agrega un 1(uno) a res                           
			else:                         res.append("0")                             # sino se agrega un 0(cero)
			c += 1                                                                    # se incrementa el contador en uno
		return "".join(res)             #  se retorna la lista en forma de cadena invertida	
	#==============================================================================================================================================================================	
	def OR(self, a, b):
		lista , res , c  = [] , [] , 0                                             #  establecemos 3 variables --- 2 listas vacias y 1 contador
		for x in range(len(a)):             lista.append( [int(a[x]),int(b[x])] )  #  agrego a la lista, otra lista con 2 bits (uno de cada numero binario)                
		while c < 32:                                                              #  mientras c < 32 . . .
			if sum(lista[c]) == 0:        res.append("0")                             # si los 2 bits son 0(cero) se agrega un 0(cero) a res                           
			else:                         res.append("1")                             # sino se agrega un 1(uno)
			c += 1                                                                    # se incrementa el contador en uno
		return "".join(res)             #  se retorna la lista en forma de cadena invertida			
	#==============================================================================================================================================================================
	def NOT(self, n1):
		lis = []
		for x in n1 :           #  recorremos el numero y lo invertimos (si es un 1 agregamos un cero)y (si es un cero agregamos un uno)
			if x == "1":    lis.append("0")
			if x == "0":    lis.append("1")
		return "".join(lis)              #  retornamos la lista --- en forma de cadena 
	#==============================================================================================================================================================================
	#----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----

class Main(ENTRADA_SALIDA, ALU):      #  esta clase heredad de la clase ENTRADA_SALIDA y de la clase ALU 
	#==============================================================================================================================================================================
	def __init__(self):
		pygame.init()                                                        #  iniciamos pygame
		self.pantalla = pygame.display.set_mode((950,600),FULLSCREEN)        #  pantalla completa
		#~ self.pantalla = pygame.display.set_mode((950,600),0)              #  pantalla 950 x 600
		self.cadena , self.cargar_input , self.pos , self.resultado = "" , -1 , (0,0) , ""
		#~ -----------------------------------------------------------------------------------------------------------------------------------------------------
		#    IMAGENES BOTONES		
		self.boton_suma = "BOTONES/suma_1.jpg", "BOTONES/suma_2.jpg"
		self.boton_resta = "BOTONES/resta_1.jpg", "BOTONES/resta_2.jpg"
		self.boton_and = "BOTONES/and_1.jpg", "BOTONES/and_2.jpg"
		self.boton_or = "BOTONES/or_1.jpg", "BOTONES/or_2.jpg"
		self.boton_not = "BOTONES/not_1.jpg", "BOTONES/not_2.jpg"
		self.boton_salir = "BOTONES/salir_1.jpg", "BOTONES/salir_2.jpg"
		self.boton_memoria = "BOTONES/memoria_1.jpg", "BOTONES/memoria_2.jpg"
		self.boton_inicio = "BOTONES/inicio_1.jpg", "BOTONES/inicio_2.jpg"
		#~ -----------------------------------------------------------------------------------------------------------------------------------------------------
		self.fuente =[ pygame.font.SysFont("Times New Roman", 35),pygame.font.SysFont("Times New Roman", 45),pygame.font.SysFont("Times New Roman", 80) ]
		#~ -----------------------------------------------------------------------------------------------------------------------------------------------------
		ram = open("RAM.txt","w")		   										#  creamos el archivo "RAM.txt" 
		for i in range(4096):		ram.write(self.DECIMAL_A_BINARIO(0)+"\n")       #  completo la memoria con 50 palabras ( todas con 0 )
		ram.close()                                       						#  cerramos el archivo para que se guarden los cambios
	#==========================================================================================================================================================
	def INICIO(self):
		self.cadena , self.cargar_input ,self.pos = "", -1, (0,0)		
		self.MOSTRAR_IMAGEN("FONDO/black.jpg",(0,0)),     self.IMPRIMIR_texto(" ARQUITECTURA VON NEUMANN ",(180,15), self.fuente[0], "gold")
		self.IMPRIMIR_texto(" Haga click en la opcion deseada ",(225,53), self.fuente[0], "blue")
		#     CADA TUPLA CONTIENE (6 elementos)...  un metodo sin los() , una tupla con 2 imagenes, los limites del boton x1,x2,y1,y2 
		L = [(self.CARGAR_INPUT,self.boton_suma,370,548,100,170),(self.CARGAR_INPUT,self.boton_resta,370,548,180,250),(self.CARGAR_INPUT,self.boton_and,370,548,260,330),
		     (self.CARGAR_INPUT,self.boton_or,370,548,340,410),(self.CARGAR_INPUT,self.boton_not,370,548,420,490),(self.SALIR,self.boton_salir,370,548,500,580)]
		self.EVENTO_mouse(L)                		
	#==========================================================================================================================================================
	def OPERACION(self):
		if self.pos[1] in range(100,171): 	self.operacion = " SUMA "
		if self.pos[1] in range(180,251): 	self.operacion = " RESTA "
		if self.pos[1] in range(260,331): 	self.operacion = " AND "
		if self.pos[1] in range(340,411): 	self.operacion = " OR "
		if self.pos[1] in range(420,491):   self.operacion = " NOT "
	#==========================================================================================================================================================
	def IMPRIMIR_OPERACION(self):		
		if self.operacion == " NOT ":		self.IMPRIMIR_texto("INGRESE 1 VALOR " ,(260,50), self.fuente[1], "green")					      
		else:								self.IMPRIMIR_texto("INGRESE 2 VALORES " ,(260,50), self.fuente[1], "green")				      
	#==========================================================================================================================================================
	def PRINT_cadena(self, cadena, pos_x, pos_y):																				    		#      
		pygame.draw.rect(self.pantalla,(0,0,0),( pos_x-5, pos_y-8, 600, 60 ),0)
		self.pantalla.blit(self.fuente[0].render(cadena , True, (255,255,255),(0,0,0)),( pos_x, pos_y)),    pygame.display.flip()
	#==========================================================================================================================================================
	def MOSTRAR_IMAGEN(self, Imagen, posicion):																				    #       MOSTRAR IMAGEN
		self.pantalla.blit( pygame.image.load(Imagen), posicion),      pygame.display.flip()                  #  actualiza los cambios en pantalla
	#==========================================================================================================================================================
	def LIMPIAR_eventos(self):																									#       LIMPIAR EVENTOS
		pygame.mouse.set_visible(False), pygame.event.clear(), pygame.mouse.set_visible(True)   #  permitimos que se vea el puntero
	#==========================================================================================================================================================
	def EVENTO_mouse(self , L , si=True ):          																			#		EVENTO MOUSE
		self.LIMPIAR_eventos()           		                             #  limpiamos los eventos acumulados
		while si:                       				                     #  comienza el ciclo
			pos = pygame.mouse.get_pos()   #  devuelve la posicion del puntero (x,y)      #  pos[0] es el eje(x) --- pos[1] es el eje(y)
			#~ ------------------------------------------------------------------------------------------------------------------------------------------------
			for i in L:                                                   #   C A M B I A   L A   I M A G E N   D E   L O S   B O T O N E S 
				if pos[0] in range(i[2],i[3]) and pos[1] in range(i[4],i[5]):      #   si el puntero pasa por encima de algun boton .....
					self.MOSTRAR_IMAGEN(i[1][1],(i[2],i[4]))                              #   se cambia la imagen
				else:                                                   
					self.MOSTRAR_IMAGEN(i[1][0],(i[2],i[4]))                              #   si no se muestra la imagen original del boton
			#~ ------------------------------------------------------------------------------------------------------------------------------------------------
			for EVENTO in pygame.event.get():                                #  SE RECORREN LOS EVENTOS        
				if EVENTO.type == MOUSEBUTTONDOWN:       
					for x in L:              # L es una lista que contiene listas..... x es una lista que contiene 5 elementos (un metodo y coord x1,x2,y1,y2)           
						if pos[0] in range(x[2],x[3]) and pos[1] in range(x[4],x[5]):     #  si presione en este punto de coordenadas  . . .
							self.pos , si = pos , False
							x[0]()                                                #  x[0] corresponde a un metodo   y  le agregamos los () para que se ejecute
	#==========================================================================================================================================================
	def IMPRIMIR_texto(self,CADENA,(x,y), fuente, color, tiempo=0):																#	    IMPRIMIR TEXTO
		cadena = ""
		for letra in range(len( CADENA[:-1])):      #  letra recorre el rango de la longitud de CADENA-1
			cadena += CADENA[letra]                 #  a la variable cadena se le suma una letra
			texto = fuente.render(cadena, True, pygame.Color(color))
			self.pantalla.blit(texto,(x,y)),  pygame.display.flip() ,   sleep(tiempo)# imprimimos la cadena, actualizamos la pantalla, espera
	#==========================================================================================================================================================		
	def SALIR(self):																											#       SALIR
		self.MOSTRAR_IMAGEN("FONDO/black.jpg", (0,0)),   self.IMPRIMIR_texto("HASTA LA PROXIMA ",(85,250), self.fuente[2], "blue", (0.05)),  sleep(1),  exit()
	#==============================================================================================================================================================================
	#----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----@----
